#define VOLTARGET VolTarget7Vec

#include "VolTarget7Vec.h"


double VOLTARGET::run() const
{
    const int trials = EQMCBase::trials;
    double sum = 0.0;
#ifndef __INTEL_COMPILER
    #pragma loop( no_parallel )
#endif
#pragma ivdep
    for (int i = 0; i < trials; ++i)
    {
        //trial = i;
        sum += calcCorePayoffBi(i, false);
    }
    return sum;
}

double VOLTARGET::calcCorePayoffBi(const int trial, bool isPastPayoff) const
{
    double finalPayoff = 0.0;
#define nUnds 5
#define nObs 1424
#define nReturns 50

    //if (!isEvent(nObs, SCH2)) { throw new Exception("Error: sch2 must be present on expDate"); }
    bool isStruck = false;
    double currSum = 0.0;
    double currTW;
    double currSpot = 1.0;
    double currExp = 0.0;
    bsk[0] = 0.0;
#ifdef __INTEL_COMPILER
#pragma ivdep
#endif
    for (int t = 0; t <= nObs; ++t)
    {
        double bskSum = 0;
        for (int u = 0; u < nUnds; ++u)
        {
            bskSum += weight(u) * NS(trial, u, t) / NS(trial, u, stkIndex + 1);
            //bskSum += weight(0) * NS(trial, 0, t) / NS(trial, 0, stkIndex + 1);
            //bskSum += weight(1) * NS(trial, 1, t) / NS(trial, 1, stkIndex + 1);
            //bskSum += weight(2) * NS(trial, 2, t) / NS(trial, 2, stkIndex + 1);
            //bskSum += weight(3) * NS(trial, 3, t) / NS(trial, 3, stkIndex + 1);
            //bskSum += weight(4) * NS(trial, 4, t) / NS(trial, 4, stkIndex + 1);
        }
        bsk[t] = bskSum;
    }
    for (int t = 1; t <= nObs; t++)
    {
        if (isStruck)
        {
            currSpot = currSpot * (1.0 + currExp * (bsk[t] / bsk[t - 1] - 1.0 - yearFractions[t] * fundingRate));
            currTW = Math.Min(cap, targetVol / Math.Sqrt(currSum * annFac / weightSum));
            if (currTW < low * currExp || currTW > high * currExp)
                currExp = currTW;
            double perf = Math.Log(bsk[t - nReturns] / bsk[t - nReturns - 1]);
            currSum -= perf * perf * weights[nReturns - 1];
            currSum *= weights[0];
            double perf2 = Math.Log(bsk[t] / bsk[t - 1]);
            currSum += weights[0] * perf2 * perf2;
        }
        if (t == stkIndex)
        {
            for (int tt = 0; tt < nReturns; ++tt)
            {
                double perf = Math.Log(bsk[t - tt] / bsk[t - tt - 1]);
                currSum += weights[tt] * perf * perf;
            }
            isStruck = true;
        }
        if (isEvent(t, SCH2))
        {
            finalPayoff += currSpot;
        }
    }
    finalPayoff /= nSch2s;
    return R + p * option(finalPayoff);
}
#undef VOLTARGET
